# YunCha-Coffee PyCharm
# user 86155
# 2025/8/30 1:15
import traceback
from enum import Enum

from fastapi import APIRouter, Depends, HTTPException, status, UploadFile, File,Form,BackgroundTasks,Query
from typing import List, Optional
from pydantic import BaseModel, validator, Field
from app.models import ProductReview, User, Order, ProductTypeEnum, CoffeeProduct, MerchandiseProduct
from  datetime import datetime
from app.dependencies import get_current_user
from app.dependencies import require_admin  # 假设存在管理员验证依赖
from app.utils.file_handlers import save_upload_file, delete_file
import json
import os
from pathlib import Path
from decimal import Decimal  # 导入 Decimal 类型




productReview_api = APIRouter(prefix="/reviews")
# class ProductReviewIn(BaseModel):
#     product_id: int
#     product_type: ProductTypeEnum = Field(..., description="产品类型")
#     rating: int = Field(..., ge=1, le=5, description="评分(1-5)")
#     content: Optional[str] = Field(None, max_length=1000, description="评论内容")
#     order_id: Optional[int] = Field(None, ge=1, description="订单ID")


    # @validator('rating')
    # def validate_rating(cls, v):
    #     if v not in [1, 2, 3, 4, 5]:
    #         raise ValueError('评分必须在1-5之间')
    #     return v
# class ProductReviewOut(BaseModel):
#     id: int
#     user_id: int
#     user_name: Optional[str] = None
#     product_id: int
#     product_type: ProductTypeEnum
#     rating: int
#     content: Optional[str] = None
#     order_id: Optional[int] = None
#     is_verified: bool
#     image_urls: Optional[List[str]] = None
#     created_at: datetime
#     class Config:
#         # orm_mode = True
#         from_attributes = True

class ProductTypeEnum2(str, Enum):
    coffee = "coffee"
    merchandise = "merchandise"
class ProductReviewCreate(BaseModel):
    product_id: int
    product_type: ProductTypeEnum2
    order_id: Optional[int] = None   # 可为空
    rating: int = Field(..., ge=1, le=5)
    content: Optional[str] = None

class ProductReviewOut(BaseModel):
    id: int
    user_id: int
    product_id: int
    product_type: ProductTypeEnum2
    order_id: Optional[int]
    rating: int
    content: Optional[str]
    image_urls: Optional[List[str]]
    is_verified: bool
    created_at: datetime

    class Config:
        from_attributes = True
@productReview_api.get("/", summary="（用户端）获取产品评论列表")
async def get_reviews(
    product_id: Optional[int] = None,
    product_type: Optional[ProductTypeEnum] = None,  # 使用枚举类型
    rating: Optional[int] = None,
    page: int = 1,
    limit: int = 10
):
    """
    获取产品评论列表（基础版）
    - product_id: 按产品ID筛选
    - product_type: 按产品类型筛选（coffee-咖啡产品, merchandise-周边商品）
    - rating: 按评分筛选
    - page: 页码，默认1
    - limit: 每页数量，默认10
    """
    # 基础查询
    query = ProductReview.all().prefetch_related('user')
    # 条件筛选 - 产品ID和产品类型可以单独或组合使用
    if product_id is not None:
        query = query.filter(product_id=product_id)

    if product_type is not None:
        # 验证产品类型是否有效
        if product_type not in [ProductTypeEnum.COFFEE, ProductTypeEnum.MERCHANDISE]:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail=f"产品类型必须是 {[e.value for e in ProductTypeEnum]} 之一"
            )
        query = query.filter(product_type=product_type)

    if rating is not None:
        if rating not in [1, 2, 3, 4, 5]:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="评分必须在1-5之间"
            )
        query = query.filter(rating=rating)

    # 获取总数用于分页信息
    total = await query.count()

    # 分页处理
    offset = (page - 1) * limit
    reviews = await query.order_by('-created_at').offset(offset).limit(limit).all()

    # 转换为输出模型
    review_data = [ProductReviewOut.from_orm(review) for review in reviews]

    return {
        "code": 200,
        "message": "获取成功",
        "data": review_data  # 直接返回序列化后的评论列表
    }


@productReview_api.get("/admin", summary="（管理员）获取所有评论（支持多条件筛选）")
async def admin_get_all_reviews(
        product_id: Optional[int] = None,
        product_type: Optional[ProductTypeEnum] = None,
        user_id: Optional[int] = None,
        rating: Optional[int] = None,
        is_verified: Optional[bool] = None,
        page: int = 1,
        limit: int = 20,
        # current_admin: User = Depends(require_admin)
):
    """
    管理员获取所有评论，支持多维度筛选
    比用户端接口增加了管理员专属筛选条件
    """
    query = ProductReview.all().prefetch_related('user', 'order')

    # 多条件筛选
    if product_id:
        query = query.filter(product_id=product_id)
    if product_type:
        query = query.filter(product_type=product_type)
    if user_id:
        query = query.filter(user_id=user_id)
    if rating is not None:
        query = query.filter(rating=rating)
    if is_verified is not None:
        query = query.filter(is_verified=is_verified)


    # 总数与分页
    total = await query.count()
    offset = (page - 1) * limit
    reviews = await query.order_by('-created_at').offset(offset).limit(limit).all()

    return {
        "code": 200,
        "message": "获取成功",
        "data": {
            "reviews": [
                {
                    "id": review.id,
                    "user_id": review.user_id,
                    "user_name": review.user.username,
                    "product_id": review.product_id,
                    "product_type": review.product_type,
                    "rating": review.rating,
                    "content": review.content,
                    "image_urls": review.image_urls,
                    "is_verified": review.is_verified,
                    "created_at": review.created_at,
                } for review in reviews
            ],
            "pagination": {
                "page": page,
                "limit": limit,
                "total": total,
                "pages": (total + limit - 1) // limit if total > 0 else 0
            }
        }
    }

@productReview_api.get("/{id}",summary="（用户端）获取单个评论详情",)
async def get_review_detail(id: int):
    """获取单个评论详情"""
    review = await ProductReview.filter(id=id).prefetch_related('user').first()
    if not review:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="评论不存在"
        )
    # 使用ProductReviewOut模型序列化数据
    review_data = ProductReviewOut.from_orm(review)
    return {
        "code": 200,
        "message": "获取评论详情成功",
        "data": review_data
    }


@productReview_api.get("/product/{product_id}", summary="（用户端）获取指定产品的所有评论")
async def get_product_reviews(
        product_id: int,
        product_type: Optional[str] = None,
        page: int = 1,
        limit: int = 10,
):
    """获取指定产品的所有评论"""
    query = ProductReview.filter(product_id=product_id).prefetch_related('user')


    if product_type is not None:
        # 验证产品类型
        if product_type not in [ProductTypeEnum.COFFEE, ProductTypeEnum.MERCHANDISE]:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail=f"产品类型必须是 {[e.value for e in ProductTypeEnum]} 之一"
            )
        query = query.filter(product_type=product_type)

    # 获取总数用于分页
    total = await query.count()

    offset = (page - 1) * limit
    reviews = await query.order_by('-created_at').offset(offset).limit(limit).all()

    # 序列化数据
    review_data = [ProductReviewOut.from_orm(review) for review in reviews]

    return {
        "code": 200,
        "message": "获取产品评论成功",
        "data": {
            "product_id": product_id,
            "product_type": product_type,
            "reviews": review_data,
            "pagination": {
                "page": page,
                "limit": limit,
                "total": total,
                "pages": (total + limit - 1) // limit if total > 0 else 0
            }
        }
    }


@productReview_api.get("/type/{product_type}", summary="（用户端）按产品类型获取评论")
async def get_reviews_by_type(
        product_type: ProductTypeEnum,
        page: int = 1,
        limit: int = 10
):
    """按产品类型获取所有评论"""
    # 验证产品类型
    if product_type not in [ProductTypeEnum.COFFEE, ProductTypeEnum.MERCHANDISE]:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=f"产品类型必须是 {[e.value for e in ProductTypeEnum]} 之一"
        )

    # 获取总数用于分页
    total = await ProductReview.filter(product_type=product_type).count()

    reviews = await ProductReview.filter(product_type=product_type) \
        .prefetch_related('user') \
        .order_by('-created_at') \
        .offset((page - 1) * limit) \
        .limit(limit) \
        .all()

    # 序列化数据
    review_data = [ProductReviewOut.from_orm(review) for review in reviews]

    return {
        "code": 200,
        "message": "按产品类型获取评论成功",
        "data": {
            "product_type": product_type.value,
            "reviews": review_data,
            "pagination": {
                "page": page,
                "limit": limit,
                "total": total,
                "pages": (total + limit - 1) // limit if total > 0 else 0
            }
        }
    }


@productReview_api.get("/user/{user_id}", summary="按用户获取评论")
async def get_user_reviews(
        user_id: int,
        product_type: Optional[ProductTypeEnum] = None,  # 可选的产品类型筛选
        page: int = 1,
        limit: int = 10
):
    """获取指定用户的所有评论，可按产品类型筛选"""
    query = ProductReview.filter(user_id=user_id).prefetch_related('user')

    if product_type is not None:
        if product_type not in [ProductTypeEnum.COFFEE, ProductTypeEnum.MERCHANDISE]:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail=f"产品类型必须是 {[e.value for e in ProductTypeEnum]} 之一"
            )
        query = query.filter(product_type=product_type)

    # 获取总数用于分页
    total = await query.count()

    reviews = await query.order_by('-created_at') \
        .offset((page - 1) * limit) \
        .limit(limit) \
        .all()

    # 序列化数据
    review_data = [ProductReviewOut.from_orm(review) for review in reviews]

    return {
        "code": 200,
        "message": "获取用户评论成功",
        "data": {
            "user_id": user_id,
            "product_type": product_type.value if product_type else None,
            "reviews": review_data,
            "pagination": {
                "page": page,
                "limit": limit,
                "total": total,
                "pages": (total + limit - 1) // limit if total > 0 else 0
            }
        }
    }


@productReview_api.get("/rating/{rating_value}", summary="（用户端）按评分获取评论")
async def get_reviews_by_rating(
        rating_value: int,
        product_type: Optional[ProductTypeEnum] = None,  # 可选的产品类型筛选
        page: int = 1,
        limit: int = 10
):
    """按评分获取评论，可按产品类型筛选"""
    if rating_value not in [1, 2, 3, 4, 5]:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="评分必须在1-5之间"
        )

    query = ProductReview.filter(rating=rating_value).prefetch_related('user')

    if product_type is not None:
        if product_type not in [ProductTypeEnum.COFFEE, ProductTypeEnum.MERCHANDISE]:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail=f"产品类型必须是 {[e.value for e in ProductTypeEnum]} 之一"
            )
        query = query.filter(product_type=product_type)

    # 获取总数用于分页
    total = await query.count()

    reviews = await query.order_by('-created_at') \
        .offset((page - 1) * limit) \
        .limit(limit) \
        .all()

    # 序列化数据
    review_data = [ProductReviewOut.from_orm(review) for review in reviews]

    return {
        "code": 200,
        "message": "按评分获取评论成功",
        "data": {
            "rating": rating_value,
            "product_type": product_type.value if product_type else None,
            "reviews": review_data,
            "pagination": {
                "page": page,
                "limit": limit,
                "total": total,
                "pages": (total + limit - 1) // limit if total > 0 else 0
            }
        }
    }


@productReview_api.get("/my/reviews", summary="（用户端）获取当前用户的评论")
async def get_my_reviews(
        current_user: User = Depends(get_current_user),
        product_type: Optional[ProductTypeEnum] = None,  # 可选的产品类型筛选
        page: int = 1,
        limit: int = 10
):
    """获取当前用户的所有评论，可按产品类型筛选"""
    query = ProductReview.filter(user_id=current_user.id).prefetch_related('user')

    if product_type is not None:
        if product_type not in [ProductTypeEnum.COFFEE, ProductTypeEnum.MERCHANDISE]:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail=f"产品类型必须是 {[e.value for e in ProductTypeEnum]} 之一"
            )
        query = query.filter(product_type=product_type)

    # 获取总数用于分页
    total = await query.count()

    reviews = await query.order_by('-created_at') \
        .offset((page - 1) * limit) \
        .limit(limit) \
        .all()

    # 序列化数据
    review_data = [ProductReviewOut.from_orm(review) for review in reviews]

    return {
        "code": 200,
        "message": "获取当前用户的评论成功",
        "data": {
            "user_id": current_user.id,
            "product_type": product_type.value if product_type else None,
            "reviews": review_data,
            "pagination": {
                "page": page,
                "limit": limit,
                "total": total,
                "pages": (total + limit - 1) // limit if total > 0 else 0
            }
        }
    }


@productReview_api.get("/stats/product/{product_id}", summary="（用户端）获取产品评论统计")
async def get_product_review_stats(
    product_id: int,
    product_type: Optional[ProductTypeEnum] = None  # 改回枚举类型
):
    try:
        # 2. 无需手动验证枚举（FastAPI 会自动拦截无效值，返回 422 错误）
        query_filters = {"product_id": product_id}
        if product_type:
            # 3. 直接传入枚举成员（ORM 会自动匹配数据库中的值，如 "coffee"）
            query_filters["product_type"] = product_type.value  # 使用枚举值

        total = await ProductReview.filter(**query_filters).count()

        # 计算平均评分
        # 计算平均评分（优化后）
        avg_result = await ProductReview.filter(**query_filters).avg('rating')
        if avg_result is None:
            average_rating = 0.0  # 无评论时默认 0.0
        elif isinstance(avg_result, Decimal):
            average_rating = round(float(avg_result), 2)  # 处理 Decimal 类型
        else:
            average_rating = round(float(avg_result or 0), 2)  # 其他数字类型


        # 计算评分分布
        rating_counts = {}
        for rating in range(1, 6):
            count = await ProductReview.filter(**query_filters, rating=rating).count()
            rating_counts[f"rating_{rating}"] = count

        return {
            "code": 200,
            "message": "获取产品评论统计成功",
            "data": {
                "product_id": product_id,
                "product_type": product_type.value if product_type else "all" ,
                "total_reviews": total,
                "average_rating": average_rating,
                "rating_distribution": rating_counts
            }
        }

    except Exception as e:
        # 添加错误日志
        print(f"Error in get_product_review_stats: {str(e)}")
        raise HTTPException(status_code=500, detail="服务器内部错误")

@productReview_api.post(
    "/",
    summary="发表产品评论",
    response_model=ProductReviewOut
)
async def create_product_review(
        product_id: int = Form(...),
        product_type: ProductTypeEnum2 = Form(...),
        order_id: Optional[int] = Form(None),
        rating: int = Form(..., ge=1, le=5),
        content: Optional[str] = Form(None),
        images: Optional[List[UploadFile]] = File(None),
        user: User = Depends(get_current_user)  # 添加类型注解
):
    # 1. 校验目标商品是否存在
    if product_type == ProductTypeEnum2.coffee:
        product = await CoffeeProduct.filter(id=product_id).first()
    else:
        product = await MerchandiseProduct.filter(id=product_id).first()

    if not product:
        raise HTTPException(status_code=404, detail="商品不存在")

    # 2. 验证订单（如果提供了 order_id）
    if order_id:
        order = await Order.filter(id=order_id, user_id=user.id).first()
        if not order:
            raise HTTPException(status_code=404, detail="订单不存在或不属于当前用户")

    # 3. 上传图片（可选）
    image_paths = []  # 存储相对路径而不是完整URL
    if images:
        for img in images:
            try:
                info = await save_upload_file(img, "reviews")
                image_paths.append(info["file_path"])  # 存储相对路径而不是完整URL
            except HTTPException as e:
                # 记录错误但继续处理其他图片
                continue

    # 4. 检查是否已经评论过（可选）
    existing_review = await ProductReview.filter(
        user_id=user.id,
        product_id=product_id,
        product_type=product_type
    ).first()

    if existing_review:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="您已经评论过该商品"
        )

    # 5. 写入数据库
    review = await ProductReview.create(
        user_id=user.id,
        product_id=product_id,
        product_type=product_type,
        order_id=order_id,
        rating=rating,
        content=content,
        image_urls=image_paths or None,  # 存储相对路径
        is_verified=bool(order_id)  # 如果有订单ID，标记为已验证购买
    )

    return review


@productReview_api.delete("/{id}", summary="（用户端）删除自己的评论")
async def delete_own_review(
        id: int,
        delete_images: bool = Query(default=True, description="是否删除图片"),
        current_user: User = Depends(get_current_user)
):
    try:
        # 查询评论
        review = await ProductReview.filter(id=id, user_id=current_user.id).first()
        if not review:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="无权限删除此评论，请确认评论归属或是否已被删除"
            )

        image_urls = review.image_urls or []
        deleted_image_count = 0
        delete_errors = []
        image_delete_msg = "无图片需要删除"

        # 删除关联图片
        if delete_images and image_urls:
            for image_url in image_urls:
                try:
                    print(f"处理图片URL: {image_url}")

                    # 改进的路径处理 - 根据实际存储结构调整
                    if image_url.startswith('reviews/'):
                        file_path = Path("static") / image_url
                    elif image_url.startswith('version/'):
                        file_path = Path("static") / image_url
                    elif 'version' in image_url:
                        # 如果URL中包含version，提取文件名并放到version目录
                        if '/' in image_url:
                            filename = image_url.split('/')[-1]
                        elif '\\' in image_url:
                            filename = image_url.split('\\')[-1]
                        else:
                            filename = image_url
                        file_path = Path("static") / "version" / filename
                    else:
                        # 默认尝试两个可能的位置
                        file_path = Path("static") / "reviews" / image_url

                    print(f"尝试删除文件: {file_path}")
                    print(f"文件存在: {file_path.exists()}")

                    if file_path.exists() and file_path.is_file():
                        file_path.unlink()
                        deleted_image_count += 1
                        print(f"成功删除: {file_path}")
                    else:
                        # 检查文件是否在version目录中
                        version_path = Path("static") / "version" / image_url
                        if version_path.exists() and version_path.is_file():
                            version_path.unlink()
                            deleted_image_count += 1
                            print(f"从version目录成功删除: {version_path}")
                        else:
                            delete_errors.append(f"文件不存在: {file_path}")

                except Exception as e:
                    delete_errors.append(f"删除失败 {image_url}: {str(e)}")
                    print(f"删除错误: {e}")

        # 删除评论记录
        await review.delete()

        response_data = {
            "id": id,
            "user_id": review.user_id,
            "product_id": review.product_id,
            "deleted_images_count": deleted_image_count,
            "total_images": len(image_urls),
            "delete_images": delete_images,
            "deleted_at": datetime.now().isoformat()
        }

        if delete_errors:
            response_data["delete_errors"] = delete_errors
            return {
                "code": 207,
                "message": "评论删除成功，但部分图片删除失败",
                "data": response_data
            }

        return {
            "code": 200,
            "message": "评论删除成功",
            "data": response_data
        }

    except HTTPException as http_e:
        raise http_e
    except Exception as e:
        import traceback
        error_stack = traceback.format_exc()
        print(f"【用户端删除评论异常】评论ID：{id}，用户ID：{current_user.id}，错误信息：{str(e)}\n堆栈：{error_stack}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="服务器内部错误，评论删除失败，请稍后重试"
        ) from e



class ReviewStatusUpdate(BaseModel):
    """评论状态更新模型"""
    is_visible: Optional[bool] = None  # 是否显示
    remark: Optional[str] = None  # 管理员备注（内部使用）



@productReview_api.get("/admin/{id}", summary="（管理员）获取单个评论详情（包含更多信息）")
async def admin_get_review_detail(
        id: int,
        # current_admin: User = Depends(require_admin)
):
    """管理员获取单个评论的详细信息，包含用户和订单关联数据"""
    review = await ProductReview.filter(id=id).prefetch_related('user', 'order').first()
    if not review:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="评论不存在"
        )

    return {
        "code": 200,
        "message": "获取成功",
        "data": {
            "id": review.id,
            "user_info": {
                "id": review.user.id,
                "username": review.user.username,
                "phone": review.user.phone,  # 管理员可见的用户联系方式
                "email": review.user.email
            },
            "product_info": {
                "id": review.product_id,
                "type": review.product_type
            },
            "order_info": {
                "id": review.order.id if review.order else None,
                "order_number": review.order.order_number if review.order else None
            } if review.order else None,
            "rating": review.rating,
            "content": review.content,
            "image_urls": review.image_urls,
            "is_verified": review.is_verified,
            "created_at": review.created_at,
        }
    }



@productReview_api.delete("/admin/{id}", summary="（管理员）删除任意评论")
async def admin_delete_review(
        id: int,
        delete_images: bool = Query(True, description="是否同时删除关联图片"),
        # current_admin: User = Depends(get_admin_user)
):
    """管理员可以删除任何评论"""
    review = await ProductReview.get_or_none(id=id)
    if not review:
        raise HTTPException(status_code=404, detail="评论不存在")

    image_urls = review.image_urls or []
    deleted_image_count = 0
    delete_errors = []

    # 删除关联图片
    if delete_images and image_urls:
        for image_url in image_urls:
            try:
                print(f"处理图片URL: {image_url}")

                # 直接构建路径 - 根据您的实际存储结构调整
                if image_url.startswith('reviews/'):
                    file_path = Path("static") / image_url
                else:
                    file_path = Path("static") / "reviews" / image_url

                print(f"尝试删除文件: {file_path}")
                print(f"文件存在: {file_path.exists()}")

                if file_path.exists() and file_path.is_file():
                    file_path.unlink()
                    deleted_image_count += 1
                    print(f"成功删除: {file_path}")
                else:
                    delete_errors.append(f"文件不存在: {file_path}")

            except Exception as e:
                delete_errors.append(f"删除失败 {image_url}: {str(e)}")
                print(f"删除错误: {e}")

    # 删除评论记录
    await review.delete()

    response_data = {
        "id": id,
        "user_id": review.user_id,
        "product_id": review.product_id,
        "deleted_images_count": deleted_image_count,
        "total_images": len(image_urls),
        "delete_images": delete_images,
        "deleted_at": datetime.now().isoformat()
    }

    if delete_errors:
        response_data["delete_errors"] = delete_errors
        return {
            "code": 207,
            "message": "评论删除成功，但部分图片删除失败",
            "data": response_data
        }

    return {
        "code": 200,
        "message": "评论删除成功",
        "data": response_data}
@productReview_api.get("/admin/stats/overall", summary="（管理员）获取全平台评论统计")
async def admin_get_overall_stats(
        # current_admin: User = Depends(require_admin)
):
    """管理员获取全平台评论统计数据"""
    query = ProductReview.all()


    # 基础统计
    total_reviews = await query.count()
    verified_reviews = await query.filter(is_verified=True).count()
    average_rating = await query.avg('rating')

    # 评分分布
    rating_distribution = {}
    for rating in range(1, 6):
        rating_distribution[f"rating_{rating}"] = await query.filter(rating=rating).count()

    # 产品类型分布
    type_distribution = {}
    for product_type in ProductTypeEnum:
        type_distribution[product_type.value] = await query.filter(
            product_type=product_type
        ).count()



    return {
        "code": 200,
        "message": "获取统计数据成功",
        "data": {
            "summary": {
                "total_reviews": total_reviews,
                "verified_reviews": verified_reviews,
                "verified_rate": round(verified_reviews / total_reviews * 100, 2) if total_reviews else 0,
                "average_rating": round(float(average_rating or 0), 2)
            },
            "rating_distribution": rating_distribution,
            "product_type_distribution": type_distribution,

        }
    }
